﻿// (c)2010 David Schwarz (david.schwarz@live.com)
// This file is licensed under GNU GPL v2 license, see more at http://www.gnu.org/licenses/gpl-2.0.html
namespace Z2.Editor
{

	#region Using

	using System;
	using System.Collections.Generic;
	using System.Text;
	using System.Drawing;
	using System.Xml;
	using Z2.Common;

	#endregion

	/// <summary>
	/// Políčko mapy
	/// </summary>
	public class EditorField: IXmlObject
	{

		#region Members

		private static List<long> _ids;

		private long m_id;
		private EditorObject m_obj;

		#endregion

		#region Constructor

		/// <summary>
		/// Statický konstruktor
		/// </summary>
		static EditorField()
		{
			_ids = new List<long>();
		}

		internal EditorField()
		{
		}

		/// <summary>
		/// Konstruktor pro existující pole mapy
		/// </summary>
		/// <param name="id">Identifikátor</param>
		/// <param name="obj"><see cref="EditorObject"/></param>
		public EditorField(long id, EditorObject obj)
		{
			this.m_id = id;
			this.m_obj = obj;
			_ids.Add(id);
		}

		/// <summary>
		/// Editor pro nové pole mapy
		/// </summary>
		/// <param name="obj"><see cref="EditorObject"/></param>
		public EditorField(EditorObject obj)
		{
			// Vygenerování unikátního ID
			Random rnd = new Random();
			int id = rnd.Next(int.MinValue, int.MaxValue);
			while (_ids.Contains(id))
			{
				id = rnd.Next(int.MinValue, int.MaxValue);
			}
			_ids.Add(id);

			this.m_id = id;
			this.m_obj = obj;
		}

		#endregion

		#region Methods

		public bool ChangeID(long newId)
		{
			if (!this.IsFreeID(newId)) return false;
			_ids.Remove(this.m_id);
			_ids.Add(newId);
			this.m_id = newId;

			return true;
		}

		public bool IsFreeID(long newId)
		{
			return !_ids.Contains(newId) || (this.ID == newId && _ids.Contains(newId));
		}

		/// <summary>
		/// Metoda smaže všechny pole
		/// </summary>
		public static void Clear()
		{
			_ids.Clear();
		}

		/// <summary>
		/// Smaže toto pole
		/// </summary>
		public void Remove()
		{
			_ids.Remove(this.m_id);
			this.m_obj = null;
		}

		#endregion

		#region Properties

		public Point Location
		{
			get;
			set;
		}

		/// <summary>
		/// Vrací unikátní ID
		/// </summary>
		public long ID
		{
			get
			{
				return this.m_id;
			}
		}

		/// <summary>
		/// Vrací <see cref="EditorObject"/>
		/// </summary>
		public EditorObject EditorObject
		{
			get
			{
				return this.m_obj;
			}
		}

		#endregion

		protected static bool Exists(string name, XmlNode node)
		{
			return node.Attributes[name] != null;
		}


		/// <summary>
		/// Pomocná metoda pro vytoření Xml atributu
		/// </summary>
		/// <param name="name">Název atributu</param>
		/// <param name="value">Hodnota atributu</param>
		/// <param name="doc">Instance <see cref="XmlDocument"/></param>
		/// <returns><see cref="XmlAttribute"/></returns>
		protected static XmlAttribute CreateAttribute(string name, string value, XmlDocument doc)
		{
			XmlAttribute attribute = doc.CreateAttribute(name);
			attribute.Value = value;
			return attribute;
		}

		#region IXmlObject Members

		public virtual XmlElement Save(string name, XmlDocument doc)
		{
			XmlElement elm = doc.CreateElement(name);
			
			elm.Attributes.Append(CreateAttribute(XmlConst.ATT_ID, Convert.ToString(this.ID), doc));

			if(this.EditorObject != null)
			{
				elm.Attributes.Append(CreateAttribute(XmlConst.ATT_DEFINITION, this.EditorObject.Name, doc));
			}

			elm.Attributes.Append(CreateAttribute(XmlConst.ATT_X, Convert.ToString(this.Location.X), doc));
			elm.Attributes.Append(CreateAttribute(XmlConst.ATT_Y, Convert.ToString(this.Location.Y), doc));

			return elm;
		}

		public virtual void Load(XmlNode element)
		{
			this.m_id = Convert.ToInt64(element.Attributes[XmlConst.ATT_ID].Value);
			this.Location = new Point(
				Convert.ToInt32(element.Attributes[XmlConst.ATT_X].Value),
				Convert.ToInt32(element.Attributes[XmlConst.ATT_Y].Value));
			string def = element.Attributes[XmlConst.ATT_DEFINITION].Value.ToLower();
			if (!EditorForm.Definitions.ContainsKey(def))
			{
				throw new KeyNotFoundException(def + " not found in Editor.Definitions!");
			}
			this.m_obj = EditorForm.Definitions[def];
			_ids.Add(this.m_id);
		}

		#endregion
	}
}
